﻿using System.Diagnostics;

namespace RealidadeAumentada.Entidades
{
    public class ERetangulo
    {
        public int x;
        public int y;
        public int w;
        public int h;

        #region Setar Valor
        public void SetarValor(ERetangulo i_source)
        {
            this.x = i_source.x;
            this.y = i_source.y;
            this.h = i_source.h;
            this.w = i_source.w;
        }
        #endregion

        #region Setar a Área do Retângulo
        public void SetarAreaRetangulo(EPontoDuplo2D[] i_vertex, int i_num_of_vertex)
        {
            int xmax, xmin, ymax, ymin;
            xmin = xmax = (int)i_vertex[i_num_of_vertex - 1].x;
            ymin = ymax = (int)i_vertex[i_num_of_vertex - 1].y;
            for (int i = i_num_of_vertex - 2; i >= 0; i--)
            {
                if (i_vertex[i].x < xmin)
                {
                    xmin = (int)i_vertex[i].x;
                }
                else if (i_vertex[i].x > xmax)
                {
                    xmax = (int)i_vertex[i].x;
                }
                if (i_vertex[i].y < ymin)
                {
                    ymin = (int)i_vertex[i].y;
                }
                else if (i_vertex[i].y > ymax)
                {
                    ymax = (int)i_vertex[i].y;
                }
            }
            this.h = ymax - ymin + 1;
            this.x = xmin;
            this.w = xmax - xmin + 1;
            this.y = ymin;
        }

        public void SetarAreaRetangulo(EPontoInteiro2D[] i_vertex, int i_num_of_vertex)
        {
            int xmax, xmin, ymax, ymin;
            xmin = xmax = (int)i_vertex[i_num_of_vertex - 1].x;
            ymin = ymax = (int)i_vertex[i_num_of_vertex - 1].y;
            for (int i = i_num_of_vertex - 2; i >= 0; i--)
            {
                if (i_vertex[i].x < xmin)
                {
                    xmin = (int)i_vertex[i].x;
                }
                else if (i_vertex[i].x > xmax)
                {
                    xmax = (int)i_vertex[i].x;
                }
                if (i_vertex[i].y < ymin)
                {
                    ymin = (int)i_vertex[i].y;
                }
                else if (i_vertex[i].y > ymax)
                {
                    ymax = (int)i_vertex[i].y;
                }
            }
            this.h = ymax - ymin + 1;
            this.x = xmin;
            this.w = xmax - xmin + 1;
            this.y = ymin;
        }
        #endregion

        #region Recortar
        public void clip(int i_left, int i_top, int i_right, int i_bottom)
        {
            int x = this.x;
            int y = this.y;
            int r = x + this.w - 1;
            int b = y + this.h - 1;
            if (x < i_left)
            {
                x = i_left;
            }
            else if (x > i_right)
            {
                x = i_right;
            }
            if (y < i_top)
            {
                y = i_top;
            }
            else if (y > i_bottom)
            {
                y = i_bottom;
            }
            int l;
            l = (r > i_right) ? i_right - x : r - x;
            if (l < 0)
            {
                this.w = 0;
            }
            else
            {
                this.w = l + 1;
            }
            l = (b > i_bottom) ? i_bottom - y : b - y;
            if (l < 0)
            {
                this.h = 0;
            }
            else
            {
                this.h = l + 1;
            }
            this.x = x;
            this.y = y;
            return;
        }
        #endregion

        #region Ponto Interno
        public bool EhPontoInterno(int i_x, int i_y)
        {
            int x = i_x - this.x;
            int y = i_y - this.y;

            return (0 <= x && x < this.w && 0 <= y && y < this.h);
        }
        public bool EhPontoInterno(EPontoDuplo2D i_pos)
        {
            int x = (int)i_pos.x - this.x;
            int y = (int)i_pos.y - this.y;
            return (0 <= x && x < this.w && 0 <= y && y < this.h);
        }
        public bool EhPontoInterno(EPontoInteiro2D i_pos)
        {
            int x = i_pos.x - this.x;
            int y = i_pos.y - this.y;
            return (0 <= x && x < this.w && 0 <= y && y < this.h);
        }
        #endregion

        #region Retângulo Interno
        public bool isInnerRect(ERetangulo i_rect)
        {
            Debug.Assert(i_rect.w >= 0 && i_rect.h >= 0);

            int lx = i_rect.x - this.x;
            int ly = i_rect.y - this.y;
            int lw = lx + i_rect.w;
            int lh = ly + i_rect.h;

            return (0 <= lx && lx < this.w && 0 <= ly && ly < this.h && lw <= this.w && lh <= this.h);
        }

        public bool isInnerRect(int i_x, int i_y, int i_w, int i_h)
        {
            Debug.Assert(i_w >= 0 && i_h >= 0);

            int lx = i_x - this.x;
            int ly = i_y - this.y;
            int lw = lx + i_w;
            int lh = ly + i_h;

            return (0 <= lx && lx < this.w && 0 <= ly && ly < this.h && lw <= this.w && lh <= this.h);
        }
        #endregion

        #region Diferença de Pontos Diagonais em Quadrado
        public int DiferencaPontosDiagonaisQuadrado(ERetangulo i_rect2)
        {
            int w1, w2;
            int ret;
            w1 = this.x - i_rect2.x;
            w2 = this.y - i_rect2.y;
            ret = w1 * w1 + w2 * w2;
            w1 += this.w - i_rect2.w;
            w2 += this.h - i_rect2.h;
            ret += w1 * w1 + w2 * w2;
            return ret;
        }
        #endregion

        #region Obter Distância de um Quadrado na Diagonal
        public int ObterDistanciaQuadradoDiagonal()
        {
            int lh = this.h;
            int lw = this.w;
            return lh * lh + lw * lw;
        }
        #endregion
    }
}
